package com.skyolder.milkbee.web.websocket;

import java.security.Principal;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.Timer;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

import javax.inject.Inject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.ApplicationListener;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.messaging.simp.SimpMessageSendingOperations;
import org.springframework.messaging.simp.annotation.SubscribeMapping;
import org.springframework.messaging.simp.stomp.StompHeaderAccessor;
import org.springframework.stereotype.Controller;
import org.springframework.web.socket.messaging.SessionDisconnectEvent;

import com.skyolder.milkbee.domain.Leaguer;
import com.skyolder.milkbee.domain.Message;
import com.skyolder.milkbee.domain.User;
import com.skyolder.milkbee.dto.Coder;
import com.skyolder.milkbee.dto.MyMessage;
import com.skyolder.milkbee.dto.RecvMsg;
import com.skyolder.milkbee.mq.Instant;
import com.skyolder.milkbee.mq.Producer;
import com.skyolder.milkbee.security.SecurityUtils;
import com.skyolder.milkbee.service.LeaguerService;
import com.skyolder.milkbee.service.MessageService;
import com.skyolder.milkbee.service.UserService;
import com.skyolder.milkbee.tool.StringUtil;

@Controller
public class InstantService implements ApplicationListener<SessionDisconnectEvent> {

	private static final Logger log = LoggerFactory.getLogger(InstantService.class);

	private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
	//private ConcurrentHashMap<Long, ConcurrentLinkedQueue<MyMessage>> messagesMap = new ConcurrentHashMap<Long, ConcurrentLinkedQueue<MyMessage>>();
	private ConcurrentHashMap<String,String> login2code=new  ConcurrentHashMap<String,String>();
	@Inject
	SimpMessageSendingOperations messagingTemplate;
	@Inject
	UserService userService;
	@Inject
	LeaguerService leaguerService;
	@Inject
	MessageService messageService;
	@Inject 
	Producer producer;
	
	Timer mytimer = new Timer();
	
	//@SendTo("/topic/instant/{token}")
	//@SendToUser(value = "/topic/instant",broadcast = false)

	@SubscribeMapping("/topic/code")
	public void setcode(@Payload  Coder coder,StompHeaderAccessor stompHeaderAccessor,
			Principal principal){
		login2code.put(principal.getName(), coder.getCode());
	}
	@SubscribeMapping("/topic/message")
	public void rcvMessage(@Payload RecvMsg recvMsg, StompHeaderAccessor stompHeaderAccessor, Principal principal) {
		Message message = null;
		if (recvMsg == null || StringUtil.isBlank(recvMsg.getContent())) {
			return;
		}
		String[] strings = recvMsg.getContent().split(" ");
		if (strings.length < 2) {
			return;
		}
		String rcv = strings[0];
		char at = rcv.charAt(0);
		if (at != '@') {
			return;
		}
		rcv = rcv.substring(1);// 取 @后
		Optional<User> orecver = userService.getUserWithAuthoritiesByLogin(rcv);
		if (!orecver.isPresent()) {
			return;
		}
		message = convert(recvMsg.getContent());
		message = messageService.save(message);
		
		MyMessage heMessage = convert(message);
		MyMessage meMessage = convert(message);
		
		meMessage.setMe(true);
		String mecode=login2code.get(principal.getName());
		//messagingTemplate.convertAndSendToUser(mecode, "/instant", meMessage);
		producer.send(new Instant(mecode,meMessage));
		String hecode=login2code.get(orecver.get().getLogin());
		if(!StringUtil.isBlank(hecode)){
			//messagingTemplate.convertAndSendToUser(hecode, "/instant", heMessage);
			producer.send(new Instant(hecode,heMessage));
		}
		
	}

	@Override
	public void onApplicationEvent(SessionDisconnectEvent event) {

	}

	private MyMessage convert(Message msg) {
		/*
		 * (Long id, String fromUserName, String toUserName, Long fromUserId,
		 * Long toUserId, String content,ZonedDateTime createdAt)
		 */
		MyMessage myMessage = new MyMessage(msg.getId(), null, null, msg.getFromUserId(), msg.getToUserId(),
				msg.getContent(), msg.getCreatedAt());
		User frmUser = userService.getUserWithAuthorities(msg.getFromUserId());
		if (frmUser != null) {
			myMessage.setFromUserName(frmUser.getLogin());
		}
		User toUser = userService.getUserWithAuthorities(msg.getToUserId());
		if (toUser != null) {
			myMessage.setToUserName(toUser.getLogin());
		}
		return myMessage;
	}

	private Message convert(String content) {
		Optional<User> ouser = userService.getUserWithAuthoritiesByLogin(SecurityUtils.getCurrentUserLogin());
		User me = ouser.get();
		Leaguer meleaguer = leaguerService.findByUser(me);
		Message message = new Message();
		String[] strings = content.split(" ");
		String rcv = strings[0];
		rcv = rcv.substring(1);
		Optional<User> orecver = userService.getUserWithAuthoritiesByLogin(rcv);
		if (orecver.isPresent()) {
			User he = orecver.get();
			Leaguer heleaguer = leaguerService.findByUser(he);
			message.setToLeaguerId(heleaguer.getId());
			message.setToUserId(he.getId());
		}
		StringBuilder stringBuilder = new StringBuilder();
		for (int i = 1; i < strings.length; ++i) {
			stringBuilder.append(strings[i]);
		}
		message.setContent(stringBuilder.toString());
		message.setCreatedAt(ZonedDateTime.now());
		message.setFromLeaguerId(meleaguer.getId());
		message.setFromUserId(me.getId());

		return message;
	}
}
